﻿/*
 * LINQ to LDAP
 * http://linqtoldap.codeplex.com/
 * 
 * Copyright Alan Hatter (C) 2010-2012
 * alan.hatter@gmail.com - http://hattercoding.blogspot.com/
 * 
 * This project is subject to licensing restrictions. Visit http://linqtoldap.codeplex.com/license for more information.
 */

using System;
using System.Linq;

namespace LinqToLdap.Mapping
{
    using System.Collections.Generic;

    /// <summary>
    /// Generates a class map via convention.  Property names will map directly to their attribute names.
    /// </summary>
    /// <typeparam name="T">Class to map</typeparam>
    public class AutoClassMap<T> : ClassMap<T> where T : class 
    {
        /// <summary>
        /// Creates a class map.
        /// </summary>
        /// <param name="namingContext">Naming context</param>
        /// <param name="objectCategory">Object category</param>
        /// <param name="objectClass">Object class</param>
        public AutoClassMap(string namingContext, string objectCategory = null, IEnumerable<string> objectClass = null)
        {
            NamingContext(namingContext);
            ObjectCategory(objectCategory);
            ObjectClasses(objectClass);

            var type = typeof(T);

            var properties = IsForAnonymousType
                                 ? type.GetProperties(Flags)
                                 : type.GetProperties(Flags)
                                    .Where(p => p.GetGetMethod() != null && p.GetSetMethod() != null);

            properties.ToList().ForEach(p => MapNonGeneric(p, p.Name.Equals("DistinguishedName", StringComparison.OrdinalIgnoreCase) || p.Name.Equals("entrydn", StringComparison.OrdinalIgnoreCase),
                p.Name.Equals("cn", StringComparison.OrdinalIgnoreCase) || p.Name.Equals("ou", StringComparison.OrdinalIgnoreCase)));
        }
    
        /// <summary>
        /// Converts the mapping to functional object mapping.
        /// </summary>
        /// <returns></returns>
        public override IObjectMapping ToObjectMapping()
        {
            return IsForAnonymousType
                       ? new AnonymousObjectMapping<T>(GetNamingContext(),
                                                       PropertyMappings.Select(pm => pm.ToPropertyMapping()),
                                                       GetObjectCategory(),
                                                       GetObjectClass())
                       : base.ToObjectMapping();
        }
    }
}
